<?PHP

function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}

function replaceTag($tag, $array)
{
	
	if(isset($array[$tag]))
		return $array[$tag];
	else
	{
		echo "Error: unable to find $tag.";
		return "{{".$tag."}}";
	}
}
	

	function evalConditionTags($string, $resources)
	{
		$position = 0;
		$current_master_id = -1;
		$error = false;
		$condition_map = array();
		$master_nodes = array();
		$maxlen = strlen($string)+1;
		$isif = 0;
		$iselif = 0;
		$iselse = 0;
		$isendif = 0;
		//
		while(true)
		{
			if($isif !== 1)
				$isif = preg_match("/\{[[:space:]]*#if[[:space:]]*\[([[:alnum:][:space:]!\"#\$%&'\(\)\*\+\,\.\/\:;<=>\?@\\\^_`\|~\-]*)\][[:space:]]*\}/", $string, $if, PREG_OFFSET_CAPTURE, (int) $position);
			if($iselif !== 1)
				$iselif = preg_match("/\{[[:space:]]*#elif[[:space:]]*\[([[:alnum:][:space:]!\"#\$%&'\(\)\*\+\,\.\/\:;<=>\?@\\\^_`\|~\-]*)\][[:space:]]*\}/", $string, $elif, PREG_OFFSET_CAPTURE, (int) $position);
			if($iselse !== 1)
				$iselse = preg_match("/\{[[:space:]]*#else[[:space:]]*\}/", $string, $else, PREG_OFFSET_CAPTURE, (int) $position);
			if($isendif !== 1)
				$isendif = preg_match("/\{[[:space:]]*#endif[[:space:]]*\}/", $string, $endif, PREG_OFFSET_CAPTURE, (int) $position);
			
			//echo("$isif, $iselif, $iselse, $isendif  ".$if[0][1]." ".$endif[0][1]."<br/>");
			
			if($isif === 1 || $iselif ===1 || $iselse === 1 || $isendif === 1)
			{
				if($if[0][1] > min($isendif ? $endif[0][1] : $maxlen, $iselif ? $elif[0][1] : $maxlen, $iselse ? $else[0][1] : $maxlen) || !$isif) //zamykajacy przed kolejnym otwierajacym
				{
					if($elif[0][1] >  min($isendif ? $endif[0][1] : $maxlen, $iselse ? $else[0][1] : $maxlen) || !$iselif)//zamykajacy przed kolejnym elif
					{
						if($else[0][1] > $endif[0][1] || !$iselse)//zamykajacy przed kolejnym else
						{
							if($current_master_id === -1)
								;//ERROR!
							$condition_map[$current_master_id]['end'] = $endif[0][1];
							if($condition_map[$current_master_id]['iselif'] || $condition_map[$current_master_id]['iselse'])
							{
								$current_master_id = $condition_map[$current_master_id]["master"];
							}
							if($current_master_id === -1)
								;//ERROR!
							$current_master_id = $condition_map[$current_master_id]["master"];
							$isendif = 0;
							$position = $endif[0][1] + strlen($endif[0][0]);
							//zamknij aktualnego if'a /elif'a
							//position update.
						}
						else //jest else przed endifem
						{
							if($current_master_id === -1)
								;//ERROR!
							$condition_map[$current_master_id]['end'] = $else[0][1];
							if($condition_map[$current_master_id]['iselif'])
							{
								$current_master_id = $condition_map[$current_master_id]["master"];
							}
							if($current_master_id === -1)
								;//ERROR!
							//else zawsze jest true.
							$new_elem = array_push($condition_map, array("condition" => "false", "start" => $else[0][1], "end" => 0,  "processed" => false, "elseifsuceed" => false, "elsesuceed" => false, "result" => false, "master" => $current_master_id, "iselif" => false, "iselse" => true, "elifs" => array(), "nestedifs" =>array(), "else" => -1));
							$new_elem--;
							$condition_map[$current_master_id]["else"] = $new_elem;
							$current_master_id = $new_elem;
							$iselse = 0;
							$position = $else[0][1] + strlen($else[0][0]);
							
								//zamknij aktualnego if'a /elif'a
								//dodaj sekcje else'a
								//zamknij sekcje else'a
								//position update.
						}
					}
					else
					{
						if($current_master_id === -1)
							;//ERROR!
						if($condition_map[$current_master_id]['iselse'])
							;//ERROR
							
						$condition_map[$current_master_id]['end'] = $elif[0][1];
						if($condition_map[$current_master_id]['iselif'])
						{
							$current_master_id = $condition_map[$current_master_id]["master"];
						}
						
						if($current_master_id === -1)
							;//ERROR!
								
						$new_elem = array_push($condition_map, array("condition" => $elif[1][0], "start" => $elif[0][1], "end" => 0, "processed" => false, "result" => false, "elseifsuceed" => false, "elsesuceed" => false, "master" => $current_master_id, "iselif" => true, "iselse" => false, "elifs" => array(), "nestedifs" =>array(), "else" => -1));
						$new_elem--;
						$condition_map[$current_master_id]["elifs"][] = $new_elem;
						$current_master_id = $new_elem;
						$iselif = 0;
						$position = $elif[0][1] + strlen($elif[0][0]);
						//Daj enda do sekcji poprzedniego if'a, elif'a. Dodaj nowa seksje elifa.
						//position update.
					}
				}
				else
				{
					$new_elem = array_push($condition_map, array("condition" => $if[1][0], "start" => $if[0][1], "end" => 0,  "processed" => false, "result" => false, "elseifsuceed" => false, "elsesuceed" => false, "master" => -1, "iselif" => false, "iselse" => false, "elifs" => array(), "nestedifs" =>array(), "else" => -1));
					$new_elem--;
					if($current_master_id === -1)
					{
						$current_master_id = $new_elem;
						$master_nodes[] = $new_elem;
					}
					else
					{
						$condition_map[$current_master_id]['nestedifs'][] = $new_elem;
						$condition_map[$new_elem]['master'] = $current_master_id;
						$current_master_id = $new_elem;
					}
					$isif = 0;
					$position = $if[0][1] + strlen($if[0][0]);
					//zagniezdzony if w ifie.
					//zmien current if'a.
				}	
			}
			else
			 break;
		}
		
		//print_r($condition_map);
		extract($resources, EXTR_SKIP);
		$delete_operations = array();
		$ile = 0;
		foreach($master_nodes as $master)
		{
			$current_node = $master;
			while($current_node != -1)
			{
				if($condition_map[$current_node]["processed"])
				{
					if($condition_map[$current_node]["result"])
					{
						$current_node = $condition_map[$current_node]["master"];
						continue;
					}
					else
					{
						if($condition_map[$current_node]['elseifsuceed'])
						{
							foreach($condition_map[$current_node]["elifs"] as $elseif_node)
							{
								$delete_operations[] = array('from' => $condition_map[$elseif_node]['start'], 'to' => $condition_map[$elseif_node]['end']);
								
								$ile++;
							}
							
							if(($else_node = $condition_map[$current_node]["else"]) != NULL)
							{
								$delete_operations[] = array('from' => $condition_map[$else_node]['start'], 'to' => $condition_map[$else_node]['end']);
								
								$ile++;
							}
							
							$current_node = $condition_map[$current_node]["master"];
							
						}
						else if(!$condition_map[$current_node]['elsesuceed'])
						{
							$elif_node = array_pop($condition_map[$current_node]["elifs"]);
							if($elif_node == NULL)
								$current_node = $condition_map[$current_node]["master"];
							else
								$current_node = $elif_node;
							
						}
						else
						{
							$current_node = $condition_map[$current_node]["master"];
						}
					}
				}
				else
				{
					if(eval("return ".$condition_map[$current_node]['condition'].";"))
					{
						$condition_map[$current_node]["processed"] = true;
						$condition_map[$current_node]["result"] = true;
						if($condition_map[$current_node]['iselif'] || $condition_map[$current_node]['iselse'])
						{
							if($condition_map[$current_node]['iselif'])
								$condition_map[$condition_map[$current_node]["master"]]['elseifsuceed'] = true;
							else
								$condition_map[$condition_map[$current_node]["master"]]['elsesuceed'] = true;
						}
						else
						{
							if(($else_node = $condition_map[$current_node]["else"]) != NULL)
							{
								$delete_operations[] = array('from' => $condition_map[$else_node]['start'], 'to' => $condition_map[$else_node]['end']);
								
								$ile++;
							}
							foreach($condition_map[$current_node]["elifs"] as $elseif_node)
							{
								$delete_operations[] = array('from' => $condition_map[$elseif_node]['start'], 'to' => $condition_map[$elseif_node]['end']);
								
								$ile++;
							}
						}
						$next_node = array_pop($condition_map[$current_node]['nestedifs']);
						if($next_node != NULL)
						{
							$current_node = $next_node;
						}
						else
						{
							$current_node = $condition_map[$current_node]["master"];
						}

						//echo "[True]. Condition:  ".$condition_map[$master]['condition'];
						//$delete_operations[] = array('from' = $condition_map[$master]['start'], 'end' = $condition_map[$master]['end']);
					}
					else
					{
						$condition_map[$current_node]["processed"] = true;
						$condition_map[$current_node]["result"] = false;
						$delete_operations[] = array('from' => $condition_map[$current_node]['start'], 'to' => $condition_map[$current_node]['end']);
						
						$ile++;
						if($condition_map[$current_node]['iselif'] or $condition_map[$current_node]['iselse'])
						{
							$current_node = $condition_map[$current_node]["master"];
						}
						else
						{
							$elif_node = array_pop($condition_map[$current_node]["elifs"]);
							
							if($elif_node == NULL)
							{
								if(($else_node = $condition_map[$current_node]["else"]) != NULL)
								{
									$condition_map[$current_node]["elsesuceed"] = true;
									$condition_map[$else_node]["condition"] = true;
									$current_node = $else_node;
									
								}
								else
								{
									$current_node = $condition_map[$current_node]["master"];
								}
							}
							else
							{
								$current_node = $elif_node;
							}
						}
					}
				}
			}
		}
		
		//deleteOperationBubbleSort //because fuck you, that's why //FIXME Please.
		$len = count($delete_operations);
		for($i = 0; $i < $len; $i++)
		{
			for($j = $i+1; $j < $len; $j++)
				if($delete_operations[$i]["from"] < $delete_operations[$j]["from"])
				{
					$tmp = $delete_operations[$i]["from"];
					$delete_operations[$i]["from"] = $delete_operations[$j]["from"];
					$delete_operations[$j]["from"] = $tmp;
					$tmp = $delete_operations[$i]["to"];
					$delete_operations[$i]["to"] = $delete_operations[$j]["to"];
					$delete_operations[$j]["to"] = $tmp;
				}
		}
		
		//print_r($delete_operations);
		for($i = 0; $i < $ile; $i++)
		{
			$string = substr($string, 0, $delete_operations[$i]['from']).substr($string,$delete_operations[$i]['to']);
			$count = $delete_operations[$i]['to'] - $delete_operations[$i]['from'];
			/*for($j =$i; $j < $ile; $j++)
			{
				$delete_operations[$i]['from']-=$count;
				$delete_operations[$i]['to']-=$count;
			}*/
		}
		
		$string = preg_replace ("/\{[[:space:]]*#if[[:space:]]*\[([[:alnum:][:space:]!\"#\$%&'\(\)\*\+\,\.\/\:;<=>\?@\\\^_`\|~\-]*)\][[:space:]]*\}/" , "" , $string);
		$string = preg_replace ("/\{[[:space:]]*#elif[[:space:]]*\[([[:alnum:][:space:]!\"#\$%&'\(\)\*\+\,\.\/\:;<=>\?@\\\^_`\|~\-]*)\][[:space:]]*\}/" , "" , $string);
		$string = preg_replace ("/\{[[:space:]]*#else[[:space:]]*\}/" , "" , $string);
		$string = preg_replace ("/\{[[:space:]]*#endif[[:space:]]*\}/" , "" , $string);
		
		return $string;
	}
?>